package utils;

import android.os.Handler;
import android.util.Log;

import com.qiniu.android.common.AutoZone;
import com.qiniu.android.common.FixedZone;
import com.qiniu.android.http.ResponseInfo;
import com.qiniu.android.storage.Configuration;
import com.qiniu.android.storage.KeyGenerator;
import com.qiniu.android.storage.Recorder;
import com.qiniu.android.storage.UpCancellationSignal;
import com.qiniu.android.storage.UpCompletionHandler;
import com.qiniu.android.storage.UpProgressHandler;
import com.qiniu.android.storage.UploadManager;
import com.qiniu.android.storage.UploadOptions;
import com.qiniu.android.storage.persistent.FileRecorder;

import org.json.JSONObject;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import application.App;

public class QiniuUploadUtils {
    private static QiniuUploadUtils qiniuUploadUtils;
    private UploadManager uploadManager;

    private QiniuUploadUtils() {
        init();
    }

    private void init() {
        String dirPath = "";//<断点记录文件保存的文件夹位置>
        Recorder recorder = null;
        try {
            recorder = new FileRecorder(dirPath);
        } catch (Exception e) {
        }

        //默认使用key的url_safe_base64编码字符串作为断点记录文件的文件名
        //避免记录文件冲突（特别是key指定为null时），也可自定义文件名(下方为默认实现)：
        KeyGenerator keyGen = new KeyGenerator() {
            public String gen(String key, File file) {
                // 不必使用url_safe_base64转换，uploadManager内部会处理
                // 该返回值可替换为基于key、文件内容、上下文的其它信息生成的文件名
                return key + "_._" + new StringBuffer(file.getAbsolutePath()).reverse();
            }
        };


        Configuration config = new Configuration.Builder()
                .chunkSize(512 * 1024)        // 分片上传时，每片的大小。 默认256K
                .putThreshhold(1024 * 1024)   // 启用分片上传阀值。默认512K
                .connectTimeout(10)           // 链接超时。默认10秒
                .useHttps(true)               // 是否使用https上传域名
                .responseTimeout(60)          // 服务器响应超时。默认60秒
                .recorder(recorder)           // recorder分片上传时，已上传片记录器。默认null
                .recorder(recorder, keyGen)   // keyGen 分片上传时，生成标识符，用于片记录器区分是那个文件的上传记录
                .zone(AutoZone.autoZone)        // 设置区域，指定不同区域的上传域名、备用域名、备用IP。
                                                //FixedZone.zone0   华东机房
                                                //FixedZone.zone1   华北机房
                                                //FixedZone.zone2   华南机房
                                                //FixedZone.zoneNa0 北美机房
                                                //自动识别上传区域
                                                //AutoZone.autoZone
                .build();

        // 重用uploadManager。一般地，只需要创建一个uploadManager对象
        uploadManager = new UploadManager(config);

    }

    public static QiniuUploadUtils getInstance() {
        if (qiniuUploadUtils == null) {
            synchronized (QiniuUploadUtils.class) {
                if (qiniuUploadUtils == null) {
                    qiniuUploadUtils = new QiniuUploadUtils();
                }
            }
        }
        return qiniuUploadUtils;
    }


    public interface  OnUploadListener {
        /** 上传完成
         * @param key
         * @param info
         * @param res
         */
        public abstract void complete(String key, ResponseInfo info, JSONObject res);

        /** 上传进度
         * @param key
         * @param percent
         */
        public void progress(String key, double percent);

        /**获取当前是否上传是否取消
         * @return
         */
        public void onCancel(boolean isCancel);
    }
    private OnUploadListener onUploadListener;
    public void setOnUploadListener(OnUploadListener onUploadListener) {
        this.onUploadListener = onUploadListener;
    }
    // 点击取消按钮，让UpCancellationSignal##isCancelled()方法返回true，以停止上传
    public void cancell() {
        isCancelled = true;
    }
    private volatile boolean isCancelled = false;

    public void uploadFile(File data, String key, String token) {
        isCancelled = false;
        UpCompletionHandler handler = new UpCompletionHandler() {
            @Override
            public void complete(String key, ResponseInfo info, JSONObject res) {
                //res包含hash、key等信息，具体字段取决于上传策略的设置
                if (info.isOK()) {
                    Logger.i("qiniu", "Upload Success");
                    if (onUploadListener != null) {
                        onUploadListener.complete(key, info, res);
                    }
                } else {
                    Logger.i("qiniu", "Upload Fail");
                    //如果失败，这里可以把info信息上报自己的服务器，便于后面分析上传错误原因
                }
                Logger.i("qiniu", key + ",\r\n " + info + ",\r\n " + res);
            }
        };

        UploadOptions options = new UploadOptions(null, null, false,
                new UpProgressHandler() {
                    public void progress(String key, double percent) {
                        Logger.i("qiniu", key + ": " + percent);
                        if (onUploadListener != null) {
                            onUploadListener.progress(key, percent);
                        }
                    }
                },
                new UpCancellationSignal() {
                    public boolean isCancelled() {
                        if(onUploadListener!=null){
                            onUploadListener.onCancel(isCancelled);
                        }
                        return isCancelled;
                    }
                });


        uploadManager.put(data, key, token, handler,
                options);



    }


    /**
     * @param data
     * @param key
     * @param token
     */
    public void uploadByteArray(byte[] data, String key, String token) {
        isCancelled = false;
        UpCompletionHandler handler = new UpCompletionHandler() {
            @Override
            public void complete(String key, ResponseInfo info, JSONObject res) {
                //res包含hash、key等信息，具体字段取决于上传策略的设置
                if (info.isOK()) {
                    Logger.i("qiniu", "Upload Success");
                    if (onUploadListener != null) {
                        onUploadListener.complete(key, info, res);
                    }
                } else {
                    Logger.i("qiniu", "Upload Fail");
                    //如果失败，这里可以把info信息上报自己的服务器，便于后面分析上传错误原因
                }
                Logger.i("qiniu", key + ",\r\n " + info + ",\r\n " + res);
            }
        };


//        params	Map<String, String>	自定义变量，key 必须以 x: 开始
//        mimeType	String	指定文件的 mimeType
        UploadOptions options = new UploadOptions(null, null, false,
                new UpProgressHandler() {
                    public void progress(String key, double percent) {
                        Logger.i("qiniu", key + ": " + percent);
                        if (onUploadListener != null) {
                            onUploadListener.progress(key, percent);
                        }
                    }
                },
                new UpCancellationSignal() {
                    public boolean isCancelled() {
                        if(onUploadListener!=null){
                            onUploadListener.onCancel(isCancelled);
                        }
                        return isCancelled;
                    }
                });


        uploadManager.put(data, key, token, handler,
                options);


    }

    //上传多张图片
    public void uploadMutliFiles(final List<String> filesUrls, final UploadMutliListener uploadMutliListener, final String Token) {
        if (filesUrls != null && filesUrls.size() > 0) {
            final int[] i = {0};
            final  List<String> keyList = new ArrayList<>();
            final String url = filesUrls.get(i[0]);
            uploadFile(url, new UploadListener() {
                @Override
                public void onUploadSuccess(String key) {
                    final UploadListener uploadListener = this;
                    Log.d("QiniuUploadUtils", "第" + (i[0] +1) + "张:" + url + "\t上传成功!");
                    i[0]++;
                    keyList.add(key);
                    //递归边界条件
                    if (i[0] < filesUrls.size()) {
                        //七牛后台对上传的文件名是以时间戳来命名，以秒为单位，如果文件上传过快，两张图片就会重名而上传失败，所以间隔1秒，保证上传成功（具体会不会失败呢？自己试一下看看）
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                uploadFile(filesUrls.get(i[0]), uploadListener,Token);
                            }
                        }, 1000);
                    } else {
                        uploadMutliListener.onUploadMutliSuccess(keyList);

                    }

                }

                @Override
                public void onUploadFail(Error error) {
                    Log.e("QiniuUploadUtils","第" + (i[0] +1) + "张上传失败!" + filesUrls.get(i[0]));
                    uploadMutliListener.onUploadMutliFail(error);
                }
            },Token);
        }
    }
    private String key = SPUtils.getInstance(App.getInstance()).getString("domain");
    //上传单个文件
    public void uploadFile(final String filePath, final UploadListener uploadListener,final String upToken) {
        if (filePath == null) return ;
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (uploadManager == null) {
                    uploadManager = new UploadManager();
                }
                String  mkey = DateUtils.getStringToDate(DateUtils.getCurrentDate())+".jpg";
                uploadManager.put(filePath, mkey, upToken,
                        new UpCompletionHandler() {
                            @Override
                            public void complete(String key, ResponseInfo respInfo,
                                                 JSONObject jsonData) {

                                if (respInfo.isOK()) {
                                    //print(jsonData.toString());
                                    uploadListener.onUploadSuccess(key);

                                } else {
                                    uploadListener.onUploadFail(new Error("上传失败" + respInfo.error));
                                }
                            }

                        }, null);
            }
        }).start();

    }

    //上传回调
    public interface UploadListener {
        void onUploadSuccess(String key);

        void onUploadFail(Error error);
    }

    //上传多张文件回调
    public interface UploadMutliListener {
        void onUploadMutliSuccess(List<String> list);

        void onUploadMutliFail(Error error);
    }

}
